package com.pactera.library.bluetooth

import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.os.Message
import com.pactera.library.bluetooth.event.BleEvent
import com.pactera.library.listener.ConnectCallback
import com.pactera.library.listener.OnDataReceiveListener
import com.pactera.library.listener.OnDataReceiveServerSocketListener
import com.pactera.library.utils.BleUtils
import com.pactera.library.utils.SerialDataUtils
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.*
import kotlin.concurrent.thread
import kotlin.jvm.Synchronized

/**
 * @author ypk
 * 创建日期：2021/9/10  14:29
 * 描述：传统蓝牙管理类
 */
public val OPEN_BLE_REQUESTCODE = 472;

class Ble private constructor() {
    private val bluetoothAdapter: BluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

    private val MY_UUID = UUID.fromString("abcd1234-ab12-ab12-ab12-abcdef123456") //关键参数,通信用的uuid
    private var connectRetryCount = 3; //连接失败重试次数
    private var connectRetryInterval = 0L; //连接失败重试间隔时间
    private var connectCount = 0;
    var connecting = false
    //private val handler: Handler = BleHandler.of()

    private var device: BluetoothDevice? = null
    private var clientSocket: BluetoothSocket? = null

    fun getDefaultAdapter(): BluetoothAdapter {
        return bluetoothAdapter
    }

    fun enableBLE() {
        //静默打开
        if (!bluetoothAdapter.isEnabled) {
            //若没打开则打开蓝牙
            bluetoothAdapter.enable()
        }
    }

    fun enableBLE(activity: Activity) {
        //隐式打开，回有弹出提示框
        val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        activity.startActivityForResult(intent, OPEN_BLE_REQUESTCODE)
    }

    fun startDiscoveryBLE() {
        if (bluetoothAdapter.isDiscovering) { //如果当前在搜索，就先取消搜索
            bluetoothAdapter.cancelDiscovery()
        }
        bluetoothAdapter.startDiscovery() //开启搜索
    }

    fun cancelDiscoveryBLE() {
        if (bluetoothAdapter.isDiscovering) { //如果当前在搜索，就先取消搜索
            bluetoothAdapter.cancelDiscovery()
        }
    }

    fun isEnableBLE(): Boolean {
        return bluetoothAdapter.isEnabled
    }


    /**
     * 发起配对请求
     */
    fun createBond(device: BluetoothDevice?): Boolean {
        cancelDiscoveryBLE();
        //已经测试，这个2个配对方法都可以。
        val result = device?.createBond();//推荐这个原生的
        //val result = ClsUtils.createBond(device1?.javaClass, device1) //通过工具类ClsUtils,调用createBond方法,进行配对
        println("ClientActivity.onCreate result=$result")
        return result ?: false;
    }


    private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                0 -> {
                    val bleEvent = msg.obj as BleEvent
                    mConnectCallback?.connectCallback(bleEvent);
                }
                1 -> {
                    val bleEvent = msg.obj as BleEvent
                    onDataReceiveListener?.onDataReceive(bleEvent.receiveData)
                }
                else -> {
                }
            }

        }
    }
    var mConnectCallback: ConnectCallback? = null
    private var onDataReceiveListener: OnDataReceiveListener? = null
    fun setOnDataReceiveListener(dataReceiveListener: OnDataReceiveListener) {
        onDataReceiveListener = dataReceiveListener
    }

    /**
     * 重点方法
     */
    fun connect(address: String?, mConnectCallback: ConnectCallback?) {
        this.mConnectCallback = mConnectCallback;

        if (clientSocket != null) {
            val mConnectEvent = BleEvent();
            val mMessage = Message();
            mMessage.what = 0
            mConnectEvent.connectMsg = "已经建立连接"
            mConnectEvent.connectResult = true
            mMessage.obj = mConnectEvent
            mHandler.sendMessage(mMessage)
            return
        }

        //验证蓝牙 地址的格式 是否正确
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            BleUtils.i(TAG, "the device address is invalid")
            val mConnectEvent = BleEvent();
            val mMessage = Message();
            mMessage.what = 0
            mConnectEvent.connectMsg = "蓝牙地址的格式不正确"
            mConnectEvent.connectResult = false
            mMessage.obj = mConnectEvent
            mHandler.sendMessage(mMessage)
            return
        }
        //如果当前在搜索，就先取消搜索
        cancelDiscoveryBLE()

        thread {
            connectCount = 0
            connecting = true
            var connected = false
            // BleUtils.i(TAG, "connectDevice connected=$connected connectCount=$connectCount connected=$connected")
            while (!connected && connectCount <= connectRetryCount && connecting) {
                BleUtils.i(
                    TAG,
                    "connectDevice 连接次数 connectCount=$connectCount connectRetryInterval=$connectRetryInterval"
                )
                if (connectRetryInterval > 0) {
                    try {
                        Thread.sleep(connectRetryInterval)
                    } catch (e: InterruptedException) {
                        e.printStackTrace()
                    }
                    BleUtils.i(TAG, "connectDevice  延时间隔已到，再次连接")
                }
                connected = connectDevice(address);
            }
            val mMessage = Message();
            mMessage.what = 0
            val mConnectEvent = BleEvent();
            mConnectEvent.connectMsg = "连接成功"
            mConnectEvent.connectResult = connected
            mMessage.obj = mConnectEvent
            mHandler.sendMessage(mMessage)
        }
    }

    private fun connectDevice(address: String?): Boolean {
        try {
            if (device == null) {
                device = bluetoothAdapter?.getRemoteDevice(address) //获得远程设备
            }
            if (clientSocket == null) {
                clientSocket = device?.createRfcommSocketToServiceRecord(MY_UUID) //创建客户端蓝牙Socket
                clientSocket?.connect() //开始连接蓝牙之前，注意要先配对成功！！
                BleUtils.i(TAG, "connectDevice 连接成功")
                return true
            }
        } catch (e: Exception) {
            e.printStackTrace()
            BleUtils.i(TAG, "onCreate: 异常 msg=" + e.message)
            connectCount++
            clientSocket?.close()
            clientSocket = null
            return false
        }
        return false
    }
    /**
     * 已经建立连接，建议：只有在完成退出或者再次重新建立连接时，才调用此关闭方法
     */
    fun closeConnect() {
        try {
            clientSocket?.close()
            clientSocket = null
            device=null;
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            BleUtils.i(TAG, "closeConnect 异常 msg=$e")
        } finally {
            isStop = true;
            connecting = false
        }
    }



    /**
     * 写入十六进制的数据
     */
    fun writeData(cmd: String): Boolean {
        BleUtils.i(TAG, "发送= $cmd")
        val mByteArray: ByteArray = SerialDataUtils.HexToByteArr(cmd)
        var result = true
        try {
            val mOutputStream: OutputStream =
                clientSocket?.outputStream ?: return false //获得输出流（客户端指向服务端输出文本）
            mOutputStream?.write(mByteArray)
        } catch (e: IOException) {
            e.printStackTrace()
            result = false
        }
        return result
    }

    @Volatile
    var isStop: Boolean = false

    fun readData() {
        thread {
            val mInputStream: InputStream? = clientSocket?.inputStream //获得输出流（客户端指向服务端输出文本）
            while (!isStop) {//&&!isInterrupted
                var size = 0
                try {
                    if (mInputStream == null) return@thread

                    var count = 0
                    while (count == 0) {
                        count = mInputStream.available()
                    }
                    val buffer = ByteArray(count) //512    // mInputStream.available()

                    size = mInputStream?.read(buffer)
                    if (size > 0) {
                        val buffer2 = ByteArray(size)
                        for (i in 0 until size) {
                            buffer2[i] = buffer[i]
                        }
                        val receiveString = SerialDataUtils.ByteArrToHex(buffer).trim()
                        println("Ble.readData receiveString=$receiveString")
                        val mMessage = Message();
                        mMessage.what = 1
                        val bleEvent = BleEvent()
                        bleEvent.receiveData = receiveString;
                        mMessage.obj = bleEvent
                        mHandler.sendMessage(mMessage)
                        /* if (null != onDataReceiveListener) {
                             onDataReceiveListener.onDataReceive(buffer2, size)
                         }*/
                    }
                    Thread.sleep(100) //延时 100 毫秒
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    return@thread
                }
            }
        }
    }


    //服务端socket start
    private var onDataReceiveServerSocketListener: OnDataReceiveServerSocketListener? = null
    fun setOnDataReceiveServerSocketListener(dataReceiveListener: OnDataReceiveServerSocketListener) {
        onDataReceiveServerSocketListener = dataReceiveListener
    }

    private val NAME = "Bluetooth_Socket"
    var serverSocket: BluetoothServerSocket? = null
    var socket: BluetoothSocket? = null

    @Volatile
    var isStopServerSocket: Boolean = false

    private inner class ReadThread : Thread() {
        override fun run() {
            super.run()
            serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID)
            socket = serverSocket?.accept()
            val mInputStream: InputStream? = socket?.inputStream //获得输出流（客户端指向服务端输出文本）
            while (!isStopServerSocket && !isInterrupted) {
                var size = 0
                try {
                    if (mInputStream == null) return

                    var count = 0
                    while (count == 0) {
                        count = mInputStream.available()
                    }
                    val buffer = ByteArray(count) //512    // mInputStream.available()

                    size = mInputStream?.read(buffer)
                    if (size > 0) {
                        val buffer2 = ByteArray(size)
                        for (i in 0 until size) {
                            buffer2[i] = buffer[i]
                        }
                        val receiveString = SerialDataUtils.ByteArrToHex(buffer).trim()
                        println("Ble.readData receiveString=$receiveString")
                        /*val mMessage = Message();
                         mMessage.what = 2
                         val bleEvent = BleEvent()
                         bleEvent.receiveData = receiveString;
                         mMessage.obj = bleEvent
                         mHandler.sendMessage(mMessage)*/
                        onDataReceiveServerSocketListener?.onDataReceive(receiveString)
                    }
                    sleep(100) //延时 100 毫秒
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    return
                }
            }
        }
    }

    fun startReadServerSocketThread() {
        /*try {
            val mReadThread = ReadThread()
            isStopServerSocket = false;
            mReadThread.start();
            ToastUtil.showToast("服务Socket线程初始化成功")
        } catch (e: Exception) {
            e.printStackTrace()
            ToastUtil.showToast("服务Socket线程初始化失败")
        }*/

    }

    fun closeServerSocket() {
        try {
            serverSocket?.close()
            socket = null
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            BleUtils.i(TAG, "closeServerSocket 异常 msg=$e")
        } finally {
            isStopServerSocket = true;
        }
    }

    //服务端socket end




    /**
     * 获取已经配对的蓝牙设备
     */
    fun getPairedDevices(): String? {
        val sb = StringBuffer()
        val pairedDevices: Set<BluetoothDevice> = bluetoothAdapter?.getBondedDevices()!!
        if (pairedDevices.size > 0) {
            for (device in pairedDevices) {
                sb.append("已经配对：" + device.name + ":" + device.address + " ")
            }
        }
        return sb.toString()
    }


    companion object {
        private const val TAG = "Ble"
        private lateinit var mBleManager: Ble
        private var mContext: Context? = null

        @Synchronized
        fun getInstance(context: Context?): Ble {
            if (!this::mBleManager.isInitialized || mBleManager == null) {
                mContext = context
                mBleManager = Ble()
                mBleManager.startReadServerSocketThread()
            }
            return mBleManager
        }
    }


}